package simulatorUS;

import simulatorUS.USParam.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;

import javax.swing.JButton;

enum ButtonsName {
	btnConn,
	btnBit,
	btnSelfcal,
	btnDbill,
	btnSparam,
	btnQparam,
	btnVersion,
	btnStartcm,
	btnStopall,
	btnStartvcm,
	btnSelfCal
}

public class US_EventHandler extends SystemEventHandler {
	private final static int USART_TIMEOUT_MS = 170;

	private final String DEFAULT_SENS_FOUND_STRING = "US sensor board was found on ";
	private final String DEFAULT_SENS_WASN_T_FOUND_STRING = "US sensor board wasn't found!";
	private final String DEFAULT_SENS_DISCONNECTED_STRING = "Sensor was disconnected!";
	private SystemCommand sendedComm;
	private String executorName;
	private boolean enableCommData = false;

	@Override
	public void eventOccured(SystemEvent event) {
		Date date = Calendar.getInstance().getTime();
		Formatter time = new Formatter();
		time.format(" (%tT)", date);

		switch (event.getID()) {
		case SensEventID.USART_MESSAGE_RECEIVED:
			executorName = "mainFrame";
			if (event.getParams()[0].charAt(2) == CommandsMCU.OK_RESP) {
				switch (event.getParams()[0].charAt(0)) {
				case CommandsMCU.STARTCM_COMM:
				case CommandsMCU.STARTVCM_COMM:
					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.DISABLE_COMMAND_PANEL.ordinal());
					SendCommand(executorName, sendedComm);
					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.Q_PARAM_BUTTON_ENABLE.ordinal());
					SendCommand(executorName, sendedComm);
					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.VERSION_BUTTON_ENABLE.ordinal());
					SendCommand(executorName, sendedComm);
					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.STATUS_BUTTON_ENABLE.ordinal());
					SendCommand(executorName, sendedComm);

					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.STOP_ALL_BUTTON_ENABLE.ordinal());
					SendCommand(executorName, sendedComm);
					break;
				case CommandsMCU.SPARAM_COMM:
					sendedComm = new SystemCommand(
							executorsHashMap.get(executorName),
							sensFrameCommandID.DISABLE_COMMAND_PANEL.ordinal());
					SendCommand(executorName, sendedComm);
					break;
				case CommandsMCU.STOPALL_COMM:
					/*
					 * sendedComm = new SystemCommand(
					 * executorsHashMap.get(executorName),
					 * sensFrameCommandID.ENABLE_COMMAND_PANEL.ordinal());
					 * SendCommand(executorName, sendedComm);
					 */
					break;
				}
			}
			String resp = "";
			Formatter f = new Formatter();
			if (enableCommData) {
				resp += "->";
				byte[] bytebuf = event.getParams()[0].getBytes();
				for (Byte b : bytebuf) {

					f.format("0x%x ", b);
				}
				resp += f.toString().toUpperCase() + "\n";
				resp = resp.replace('X', 'x');
			}
			resp += "-> " + parseUsartMessage(event.getParams()[0]);
			executorName = "mainFrame";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.ADD_TEXT.ordinal(), resp + time + "\n");
			break;
		case SensEventID.US_SENS_FOUND:
			executorName = "mainFrame";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.ADD_TEXT.ordinal(), "-> "
							+ DEFAULT_SENS_FOUND_STRING + event.getParams()[0]
							+ time + "\n");
			SendCommand(executorName, sendedComm);
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.ENABLE_COMMAND_PANEL.ordinal());
			SendCommand(executorName, sendedComm);
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.STOP_ALL_BUTTON_DISABLE.ordinal());
			// SendCommand(executorName, sendedComm);
			/*
			 * sendedComm = new
			 * SystemCommand(executorsHashMap.get(executorName),
			 * sensFrameCommandID.START_BUTTON_DISABLE.ordinal());
			 * SendCommand(executorName, sendedComm); sendedComm = new
			 * SystemCommand(executorsHashMap.get(executorName),
			 * sensFrameCommandID.START_VOLATILE_BUTTON_DISABLE.ordinal());
			 */
			break;
		case SensEventID.US_SENS_DISCONNECTED:
			executorName = "mainFrame";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.ADD_TEXT.ordinal(), "-> "
							+ DEFAULT_SENS_DISCONNECTED_STRING + time);
			SendCommand(executorName, sendedComm);
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.DISABLE_COMMAND_PANEL.ordinal());
			break;
		case SensEventID.US_SENS_NOT_FOUND:
			executorName = "mainFrame";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.ADD_TEXT.ordinal(), "-> "
							+ DEFAULT_SENS_WASN_T_FOUND_STRING + time);
			SendCommand(executorName, sendedComm);
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					sensFrameCommandID.DISABLE_COMMAND_PANEL.ordinal());
			break;
		case SensEventID.CONN_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.FIND_DEVICE.ordinal(),
					String.valueOf(CommandsMCU.BIT_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING,
					String.valueOf(CommandsMCU.BIT_COMM) + " ",
					String.valueOf(USART_TIMEOUT_MS));
			break;
		case SensEventID.BIT_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.BIT_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.DBILL_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.DBILL_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.QPARAM_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.QPARAM_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.SELFCAL_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.SELFCAL_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			// commandsHashMap.put(executorName, sendedComm);
			break;
		case SensEventID.START_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.STARTCM_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;

		case SensEventID.START_VOLATILE_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.STARTVCM_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.STATUS_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.STATUS_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.VERSION_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.VERSION_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.STOP_ALL_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					String.valueOf(CommandsMCU.STOPALL_COMM)
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.ACK_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					CommandsMCU.USART_MESSAGE_ENDING);
			break;
		// case SensEventID.ONE_SHOT_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.SEND_MASSAGE.ordinal(),
		// String.valueOf(CommandsMCU.MODE_COMM) + " "
		// + String.valueOf(CommandsMCU.ONE_SHOT_MODE)
		// + CommandsMCU.USART_MESSAGE_ENDING);
		// break;
		// case SensEventID.CONTINUOUS_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.SEND_MASSAGE.ordinal(),
		// CommandsMCU.MODE_COMM + " " + CommandsMCU.CONT_MODE
		// + CommandsMCU.USART_MESSAGE_ENDING);
		// break;
		// case SensEventID.CONTINUOUS_VOL_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.SEND_MASSAGE.ordinal(),
		// String.valueOf(CommandsMCU.MODE_COMM) + " "
		// + String.valueOf(CommandsMCU.VOL_CONT_MODE)
		// + CommandsMCU.USART_MESSAGE_ENDING);
		// break;
		case SensEventID.SPARAM_PRESSED:
			executorName = "usartManager";
			sendedComm = new SystemCommand(executorsHashMap.get(executorName),
					UsartCommandID.SEND_MASSAGE.ordinal(),
					CommandsMCU.SPARAM_COMM + " " + event.getParams()[0] + " "
							+ event.getParams()[1]
							+ CommandsMCU.USART_MESSAGE_ENDING);
			break;
		case SensEventID.DISPLAY_COMM_DATA_ENABLED:
			enableCommData = true;
			executorName = null;
			sendedComm = null;
			break;
		case SensEventID.DISPLAY_COMM_DATA_DISABLED:
			enableCommData = false;
			executorName = null;
			sendedComm = null;
			break;
		// case SensEventID.US_SENS_DISCONNECTED:
		// executorName = "usartManager";
		// sendedComm = new
		// SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.FIND_DEVICE.ordinal(), USART_BIT_MESSAGE
		// + USART_MESSAGE_ENDING, USART_BIT_MESSAGE + " "
		// + USART_ACK_MESSAGE + USART_MESSAGE_ENDING,
		// String.valueOf(USART_TIMEOUT_MS));
		// SendCommand(executorName, sendedComm);
		// break;
		// case SensEventID.ONE_SHOT_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new
		// SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.FIND_DEVICE.ordinal(), USART_BIT_MESSAGE
		// + USART_MESSAGE_ENDING, USART_BIT_MESSAGE + " "
		// + USART_ACK_MESSAGE + USART_MESSAGE_ENDING,
		// String.valueOf(USART_TIMEOUT_MS));
		// SendCommand(executorName, sendedComm);
		// break;
		// case SensEventID.CONTINUOUS_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new
		// SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.FIND_DEVICE.ordinal(), USART_BIT_MESSAGE
		// + USART_MESSAGE_ENDING, USART_BIT_MESSAGE + " "
		// + USART_ACK_MESSAGE + USART_MESSAGE_ENDING,
		// String.valueOf(USART_TIMEOUT_MS));
		// SendCommand(executorName, sendedComm);
		// break;
		// case SensEventID.CONTINUOUS_VOL_MODE_SELECTED:
		// executorName = "usartManager";
		// sendedComm = new
		// SystemCommand(executorsHashMap.get(executorName),
		// UsartCommandID.FIND_DEVICE.ordinal(), USART_BIT_MESSAGE
		// + USART_MESSAGE_ENDING, USART_BIT_MESSAGE + " "
		// + USART_ACK_MESSAGE + USART_MESSAGE_ENDING,
		// String.valueOf(USART_TIMEOUT_MS));
		// SendCommand(executorName, sendedComm);
		// break;

		}
		if ((executorName != null) && (sendedComm != null))
			SendCommand(executorName, sendedComm);
		/*
		 * if (!commandsHashMap.isEmpty()) { SendCommandsFromMap(); }
		 */
		/*
		 * if (sendedComm != null) SendCommand(executorName, sendedComm);
		 */
		// CommandSende

		// event.getParam()
	}

	private String parseUsartMessage(String string) {
		String resp = "OK!";
		int paramIndex = 0;
		String paramName, paramUnit;
		String offsetStr;
		Integer errCode;
		// respMap.put(CommandsMCU.BIT_COMM, "Built In Test");
		// respMap.put(CommandsMCU.MODE_COMM, "Mode selection");
		// respMap.put(CommandsMCU.SELFCAL_COMM, "Self Calibration");
		// respMap.put(CommandsMCU.DBILL_COMM, "Double Bill Sense ");
		String message = string.substring(0, string.length() - 2);
		switch (message.charAt(0)) {
		case CommandsMCU.BIT_COMM:
		case CommandsMCU.STOPALL_COMM:
		case CommandsMCU.STARTCM_COMM:
		case CommandsMCU.STARTVCM_COMM:
			switch (message.charAt(0)) {
			case CommandsMCU.BIT_COMM:
				resp = "Built In Test";
				break;
			// case CommandsMCU.SELFCAL_COMM:
			// resp ="Self Calibration";
			// break;
			case CommandsMCU.STOPALL_COMM:
				resp = "Stop all";
				break;
			case CommandsMCU.STARTCM_COMM:
				resp = "Start continuos mode";
				break;
			case CommandsMCU.STARTVCM_COMM:
				resp = "Start volatile continuos mode";
				break;
			default:
				break;
			}
			switch (message.charAt(2)) {
			case CommandsMCU.OK_RESP:
				resp += " OK!";
				break;
			default:
				resp += " FAILURE!";
				/* resp += "\n   ERROR CODE:"+ message.substring(2); */
				break;
			}
			break;
		case CommandsMCU.SELFCAL_COMM:
			resp = "Calibration coefficient: "
					+ message.substring(2, message.length() - 1);
			break;
		case CommandsMCU.DBILL_COMM:
			resp = "Double bill detection result:";
			switch (message.charAt(2)) {
			case CommandsMCU.NO_BILLS:
				resp += " No bills detected";
				break;
			case CommandsMCU.ONE_BILL:
				resp += " Single bill detected";
				break;
			case CommandsMCU.DOUBLE_BILL:
				resp += " Double bill detected";
				break;
			case CommandsMCU.NO_CALIBRATION_DATA:
				resp += " No calibration data";
				break;
			case CommandsMCU.NOT_ABLE_TO_DECIPHER:
				resp += " Not able to decipher";
				break;
			}
			break;
		case CommandsMCU.SPARAM_COMM:
			resp = "Set parameter result:";
			switch (message.charAt(2)) {
			case CommandsMCU.SUCCESSFUL:
				resp += " Success";
				break;
			case CommandsMCU.INVALID_NUMBER:
				resp += " Invalid number";
				break;
			case CommandsMCU.OUT_OF_RANGE:
				resp += " Out of range";
				break;
			}
			break;
		case CommandsMCU.QPARAM_COMM:
			resp = "Parameter list:\n";
			offsetStr = "   ";
			for (int i = 0; i < resp.length(); i++) {
				offsetStr += " ";
			}
			message = " " + message;
			for (int paramNum = 0; paramNum < USParam.paramNames.size(); paramNum++) {
				paramName = USParam.paramNames.get(paramNum).substring(0, 1)
						+ USParam.paramNames.get(paramNum).toLowerCase()
								.substring(1);
				paramUnit = USParam.paramUnits.get(paramName.toUpperCase());
				paramIndex = message.indexOf(
						Integer.toString(paramNum).charAt(0),
						message.indexOf(' ', paramIndex)) + 2;
				resp += offsetStr + paramName + ": ";
				resp += message.substring(paramIndex,
						message.indexOf(' ', paramIndex))
						+ paramUnit + "\n";
			}
			break;
		case CommandsMCU.VERSION_COMM:
			message = message.substring(3);
			resp = "Hardware version: ";
			resp += message.split(" ")[0];
			resp += "\n   Firmware version: ";
			resp += message.split(" ")[1];
			break;

		case CommandsMCU.STATUS_COMM:
			resp = "Sensor status:\n";
			offsetStr = "";
			for (int i = 0; i < resp.length(); i++) {
				offsetStr += " ";
			}
			offsetStr += "   ";
			resp += offsetStr + "Bill presence: ";
			switch (message.charAt(2)) {
			case CommandsMCU.NO_BILLS:
				resp += " No bills";
				break;
			case CommandsMCU.ONE_BILL:
				resp += " Single bill";
				break;
			case CommandsMCU.DOUBLE_BILL:
				resp += " Double bill";
				break;
			case CommandsMCU.NO_CALIBRATION_DATA:
				resp += " No calibration data";
				break;
			case CommandsMCU.NOT_ABLE_TO_DECIPHER:
				resp += " Not able to decipher";
				break;
			default:
				break;
			}
			resp += "\n";
			int lastIndex;
			paramName = USParam.paramNames.get(1).substring(0, 1)
					+ USParam.paramNames.get(1).toLowerCase().substring(1);
			paramUnit = USParam.paramUnits.get(paramName.toUpperCase());
			resp += offsetStr + paramName + ": ";
			lastIndex = message.indexOf(' ', 4);
			resp += message.substring(4, lastIndex) + paramUnit + "\n";

			resp += offsetStr + "Double bill detection counter: ";
			lastIndex++;
			resp += message.substring(lastIndex,
					(lastIndex = message.indexOf(' ', lastIndex)))
					+ "\n";

			resp += offsetStr + "Error status: ";
			lastIndex++;
			errCode = Integer.parseInt(message.substring(lastIndex));
			switch (errCode) {
			case CommandsMCU.OK:
				resp += "NO ERROR";
				break;
			default:
				resp += "ERROR! Error code:" + errCode + " ("
						+ DecipherErrorCode(SensError.valueOf(errCode)) + ")";
				break;
			}
			break;
		case CommandsMCU.ERRCODE:
			errCode = Integer.parseInt(message.substring(2, 3));
			resp = "Error status: ";
			switch (errCode) {
			case CommandsMCU.OK:
				resp += "NO ERROR";
				break;
			default:
				resp += "ERROR! Error code:" + errCode + " ("
						+ DecipherErrorCode(SensError.valueOf(errCode)) + ")";
				break;
			}
			break;
		default:
			resp = message;
			break;

		}
		return resp;
		// TODO Auto-generated method stub

	}

	private String DecipherErrorCode(SensError value) {
		String errorDecoding;
		errorDecoding = value.name().toString().toLowerCase().replace('_', ' ');
		return errorDecoding;
	}

}
